/*
 * MineralKinetics.h
 *
 *  Created on: 21 Jul 2011
 *      Author: Allan
 */

#ifndef MINERALKINETICS_H_
#define MINERALKINETICS_H_

// C++ includes
#include <string>
#include <vector>
using namespace std;

// GeoReact includes
#include <Core/Reaction.h>
#include <Core/Kinetics.h>
#include <Utils/Types.h>

// GeoReact forward declarations
class Multiphase;

struct MineralCatalyst
{
	/// The name of the species that participate as a catalyst in the mineral equation
	string name;

	/// The index of the species that participate as a catalyst in the mineral reaction (Note: to be set up when all the species involved are known)
	Index index;

	/// The name of the physical quantity that affects the rate of mineral dissolution/precipitation, e.g. a:"activity", P:"partial-pressure"
	string quantity;

	/// The power of the quantity that affects the rate of mineral dissolution/precipitation
	double power;

	MineralCatalyst();
	MineralCatalyst(const string& name, const string& quantity, double power);
	
	bool operator==(const MineralCatalyst& mineral_catalyst) const;
	bool operator!=(const MineralCatalyst& mineral_catalyst) const;
};

struct MineralMechanism
{
	/// The kinetic rate constant of the mineral reaction at 298.15 K
	double k;

	/// The Arrhenius activation energy
	double Ea;

	/// The catalysts of the reaction, e.g., a(H[+]), P(CO2(g)), a(OH[-]), a(Fe[3+]), a(Al[3+]), etc.
	vector<MineralCatalyst> catalysts;
	
	MineralMechanism();
	MineralMechanism(double k, double Ea);
	MineralMechanism(double k, double Ea, const MineralCatalyst& catalyst);
	MineralMechanism(double k, double Ea, const vector<MineralCatalyst>& catalysts);
	
	bool operator==(const MineralMechanism& mineral_mechanism) const;
	bool operator!=(const MineralMechanism& mineral_mechanism) const;
};

class MineralKineticsInfo
{
public:
	MineralKineticsInfo();
	
	MineralKineticsInfo(const string& mineral);
	
	void
	SetMineralName(const string& mineral);
	
	void
	SetSpecificSurfaceArea(double specific_surface_area);
	
	void
	AddMineralMechanism(const MineralMechanism& mechanism);
	
	void
	SetMineralMechanisms(const vector<MineralMechanism>& mechanisms);
	
	const string
	GetMineralName() const;
	
	const double
	GetSpecificSurfaceArea() const;
	
	const vector<MineralMechanism>&
	GetMineralMechanisms() const;
	
private:
	/// The name of the mineral whose rate information is being defined
	string mineral;
	
	/// The specific surface area of the mineral
	double specific_surface_area;
	
	/// The mineral rate mechanisms of the mineral dissolution/precipitation reaction
	vector<MineralMechanism> mechanisms;
};

class MineralKinetics : public Kinetics
{
public:
	MineralKinetics();
	
	MineralKinetics(const MineralKineticsInfo& info, const Multiphase& multiphase);
	
	virtual ~MineralKinetics();
	
	virtual const double
	KineticRate(const Reaction& reaction, double T, double P, const VectorXd& n, const VectorXd& a) const;
	
	virtual const VectorXd
	DerivativeKineticRate(const Reaction& reaction, double T, double P, const VectorXd& n, const VectorXd& a) const;
	
private:
	/// The mineral species
	string mineral;
	
	/// The mineral rate mechanisms of the mineral dissolution/precipitation equation
	vector<MineralMechanism> mechanisms;
	
	/// The index of the mineral species
	Index imineral;
	
	/// The specific surface area of the mineral
	double specific_surface_area;
};

#endif /* MINERALKINETICS_H_ */
